#include "CoreSystem.h"
#include "LowLevel.h"
#include "Variable.h"
#include "Graph.h"
#include "Event.h"
#include "XMLAudioData.h"
#include "AudioTypes.h"

namespace Audio
{

	CoreSystem::CoreSystem() : m_uniqueXMLFileHandle(0), m_lowLevel(0)
	///////////////////////////////////////////////////////////////////////////////
	// Description: Core system constructor; intializes some pointers
	//
	// Recent Changes:
	// -jkern	 4/04/2007 : Modified for inter-system compatibility
	// -brasmuss 3/29/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
	}

	CoreSystem::~CoreSystem()
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 4/10/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		if(m_lowLevel) {
			m_lowLevel->Shutdown();
			m_lowLevel = NULL;
		}
	}

	bool CoreSystem::Initialize( HWND hwnd, bool for_tool )
	///////////////////////////////////////////////////////////////////////////////
	// Description: Creates the low level engine
	//
	// Recent Changes:
	// -jkern	 4/04/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		m_lowLevel = new sndcore::LowLevelCore(hwnd,1000, for_tool);
		return true;
	}

	bool CoreSystem::Update(float delta)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 3/29/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		// UPDATE AND REMOVE DEAD EVENTS
		eventlist_t::iterator iter = m_activeEvents.begin();
		while(iter != m_activeEvents.end()) {
			Event* event = *iter;
			if(event->Update(delta,this)) {
				delete event;
				iter = m_activeEvents.erase(iter);
				continue;
			}
			++iter;
		}
		m_lowLevel->Update();
		return false;
	}

	bool CoreSystem::TriggerEvent(const char* name, const XMLFileHandle xmlFile)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 4/11/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		// Get event data
		xmldatamap_t::iterator iter = m_xmlData.find(xmlFile);
		if(iter == m_xmlData.end())
			return false;

		XMLAudioData* xData = iter->second;
		handlemap_t::iterator ehand_iter = xData->m_eventHandles.find(std::string(name));
		if(ehand_iter == xData->m_eventHandles.end())
			return false;
		EventHandle eHandle = ehand_iter->second;

		eventdatamap_t::iterator event_iter = xData->m_eventPool.find(eHandle);
		EventData* eData = event_iter->second;
		Event* event = new Event;
		subeventdatamap_t::iterator sub_iter;
		// For every sub-event
		for(sub_iter = eData->m_subEvents.begin(); sub_iter != eData->m_subEvents.end(); ++sub_iter) {
			SubEventData* subData = sub_iter->second;
			handlemap_t::iterator ahand_iter = xData->m_audioFileHandles.find(subData->m_soundName);
			SubEvent* subEvent = new SubEvent(ahand_iter->second);
			// For every effect
			effectdatamap_t::iterator effect_iter;
			for(effect_iter = subData->m_effects.begin(); effect_iter != subData->m_effects.end(); ++effect_iter) {
				EffectData* effectData = effect_iter->second;
				// Get handles
				VariableHandle vHandle;
				GraphHandle gHandle;
				vHandle = GetVariableHandle(effectData->m_variable.c_str(),xmlFile);
				gHandle = GetGraphHandle(effectData->m_graph.c_str(),xmlFile);
				// Choose func
				effectfunc_t func;
				if(effectData->m_type == EFFECT_GAIN)
					func = EffectGain;
				else if(effectData->m_type == EFFECT_PAN)
					func = EffectPan;
				else if(effectData->m_type == EFFECT_DIST)
					func = EffectDist;
				else // REVERB
					func = EffectReverb;
				Effect* effect = new Effect(gHandle,vHandle,func,xmlFile);
				subEvent->AddEffect(effect);
			}
			event->AddSubEvent(subEvent,subData->m_trigger);
		}

		m_activeEvents.push_back(event);

		return true;
	}

	FileHandle CoreSystem::LoadSoundFile(const WCHAR* file)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 3/29/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		FileHandle fHandle;
		if(m_lowLevel->FileExists(file,fHandle))
			return fHandle;
		m_lowLevel->LoadSound(file,fHandle,0.0f);
		return fHandle;
	}

	FileHandle CoreSystem::LoadStreamFile(const WCHAR* file)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 3/29/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		FileHandle handle;
		m_lowLevel->LoadStream(file,handle,0.0f);
		return handle;
	}

	ChannelHandle CoreSystem::PlayFile(const WCHAR* file, bool looping, float volume)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 3/29/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		FileHandle		fHandle = 0;
		ChannelHandle	cHandle = 0;
		m_lowLevel->LoadSound(file,fHandle,0.0f);
		sndcore::Channel* channel = m_lowLevel->PlaySound(fHandle,&cHandle);
		if( channel )
		{			
			channel->SetLooping(looping);
			channel->SetGain(volume);
		}
		return cHandle;
	}

	ChannelHandle CoreSystem::PlayFile(const FileHandle& fileID, bool looping, float volume)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 3/29/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		ChannelHandle		handle	= 0;
		sndcore::Channel*	channel = m_lowLevel->PlaySound(fileID,&handle);
		if( channel )
		{
			channel->SetLooping(looping);
			channel->SetGain(volume);
			channel->AddReverbDSP(0.0f);
		}
		return handle;
	}

	void CoreSystem::UnloadSoundFile(const FileHandle& fileID)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 3/29/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		m_lowLevel->ReleaseSound(fileID);
	}

	bool CoreSystem::IsPlaying(const ChannelHandle& soundID)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 3/29/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		sndcore::Channel* channel = m_lowLevel->GetChannel(soundID);
		if(!channel)
			return false;
		//return channel->HasPlayed()?? ask danny
		return true;
	}

	void CoreSystem::PlaySound(const ChannelHandle& soundID)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 3/29/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		m_lowLevel->GetChannel(soundID);
	}

	void CoreSystem::SetVolume(const ChannelHandle& soundID, float volume)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 3/29/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		sndcore::Channel* channel = m_lowLevel->GetChannel(soundID);
		if(channel)
			channel->SetGain(volume);
	}

	sndcore::Channel* CoreSystem::GetChannel(const ChannelHandle& soundID)
	///////////////////////////////////////////////////////////////////////////////
	// Description: Gets a ptr to the channel from the low level system
	//
	// Recent Changes:
	// -brasmuss 4/3/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		return m_lowLevel->GetChannel(soundID);
	}

	void CoreSystem::StopSound(const ChannelHandle& soundID)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 3/29/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		m_lowLevel->StopChannel(soundID);
	}


/////////////////////////////////
// HIGH LEVEL INTERFACE METHODS
/////////////////////////////////
	FileHandle CoreSystem::NewSoundFile(const char* name, const char* file, XMLFileHandle xmlFile)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 4/10/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		xmldatamap_t::iterator iter = m_xmlData.find(xmlFile);
		if(iter == m_xmlData.end())
			return false;
		XMLAudioData* data = iter->second;

		std::string		cfile(file);
		std::wstring	buffer;
		for( unsigned i=0; i<cfile.length(); ++i )
			buffer += (WCHAR)cfile[i];
		
		FileHandle    handle = LoadSoundFile(buffer.c_str());
	
		data->NewAudioFile(name,file,handle);

		return handle;
	}

	FileHandle	CoreSystem::GetSoundFileHandle( bool first, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if( !xmlData )
			return 0;

		return xmlData->GetAudioFileHandle( first );
	}
	const char*	CoreSystem::GetSoundFilename(const FileHandle& handle, XMLFileHandle xmlFile)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 4/10/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		xmldatamap_t::iterator iter = m_xmlData.find(xmlFile);
		if(iter == m_xmlData.end())
			return NULL;
		XMLAudioData* data = iter->second;
		audiofilemap_t::iterator a_iter = data->m_audioFilePool.find(handle);
		if(a_iter == data->m_audioFilePool.end())
			return NULL;
		return a_iter->second->m_filename.c_str();
	}

	const char*	CoreSystem::GetSoundName(const FileHandle& handle, XMLFileHandle xmlFile)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 4/10/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		xmldatamap_t::iterator iter = m_xmlData.find(xmlFile);
		if(iter == m_xmlData.end())
			return NULL;
		XMLAudioData* data = iter->second;
		audiofilemap_t::iterator a_iter = data->m_audioFilePool.find(handle);
		if(a_iter == data->m_audioFilePool.end())
			return NULL;
		return a_iter->second->m_name.c_str();
	}

	bool CoreSystem::SetSoundFilename(const FileHandle& handle, const char* filename, XMLFileHandle xmlFile)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 4/10/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		xmldatamap_t::iterator iter = m_xmlData.find(xmlFile);
		if(iter == m_xmlData.end())
			return false;
		XMLAudioData* data = iter->second;
		audiofilemap_t::iterator a_iter = data->m_audioFilePool.find(handle);
		if(a_iter == data->m_audioFilePool.end())
			return false;
		a_iter->second->m_filename = filename;
		return true;
	}

	bool CoreSystem::SetSoundName(const FileHandle& handle, const char* name, XMLFileHandle xmlFile)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 4/10/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		xmldatamap_t::iterator iter = m_xmlData.find(xmlFile);
		if(iter == m_xmlData.end())
			return false;
		XMLAudioData* data = iter->second;
		audiofilemap_t::iterator a_iter = data->m_audioFilePool.find(handle);
		if(a_iter == data->m_audioFilePool.end())
			return false;
		a_iter->second->m_name = name;
		return true;
	}

	bool CoreSystem::RemoveSound(const FileHandle& handle, XMLFileHandle xmlFile)
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 4/11/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return false;

		return xmlData->RemoveAudioFile(handle);
	}

	unsigned CoreSystem::GetSoundFreq( const FileHandle& handle )
	{	
		sndcore::Sound* sound = m_lowLevel->GetSound(handle);
		if( !sound )
			return 0;

		return sound->GetFrequency();
	}
	unsigned CoreSystem::GetSoundBitDepth( const FileHandle& handle )
	{
		sndcore::Sound* sound = m_lowLevel->GetSound(handle);
		if( !sound )
			return 0;

		return sound->GetBitsPerSample();
	}
	unsigned CoreSystem::GetSoundChannels( const FileHandle& handle )
	{
		sndcore::Sound* sound = m_lowLevel->GetSound(handle);
		if( !sound )
			return 0;

		return sound->GetNumChannels();
	}

	int CoreSystem::GetSoundLength( const FileHandle& handle )
	{
		sndcore::Sound* sound = m_lowLevel->GetSound(handle);
		if( !sound )
			return 0;

		return sound->GetSongLength();
	}
	

	XMLAudioData* CoreSystem::GetXMLAudioData(XMLFileHandle handle)
	///////////////////////////////////////////////////////////////////////////////
	// Description: Returns a ptr to the XML data. Null if doesn't exist
	//
	// Recent Changes:
	// -brasmuss 4/11/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		xmldatamap_t::iterator iter = m_xmlData.find(handle);
		if(iter == m_xmlData.end())
			return NULL;
		return iter->second;
	}

	// Variable management
	Variable* CoreSystem::getVariableData(XMLFileHandle xmlFile, const VariableHandle& varID)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0;

		return xmlData->GetVariable(varID);
	}
	VariableHandle CoreSystem::NewVariable(const char* varName, float min, float max, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0;

		return xmlData->NewVariable(varName,min,max);
	}

	VariableHandle CoreSystem::GetVariableHandle(const char* name, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return false;
		
		VariableHandle handle = xmlData->GetVariableHandle(name);
		return handle;
	}

	VariableHandle CoreSystem::GetVariableHandle(bool first, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if( !xmlData )
			return 0;

		return xmlData->GetVariableHandle( first );
	}
	const char* CoreSystem::GetVariableName(const VariableHandle& handle, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return NULL;

		Variable* var = xmlData->GetVariable(handle);
		if(!var)
			return NULL;
		return var->m_name.c_str();
	}

	float CoreSystem::GetVariableMin(const VariableHandle& handle, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0.0f;

		Variable* var = xmlData->GetVariable(handle);
		if(!var)
			return 0.0f;
		return var->m_min;
	}

	float CoreSystem::GetVariableMax(const VariableHandle& handle, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0.0f;

		Variable* var = xmlData->GetVariable(handle);
		if(!var)
			return 0.0f;
		return var->m_max;
	}

	float CoreSystem::GetVariableValue(const VariableHandle& handle, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0.0f;

		Variable* var = xmlData->GetVariable(handle);
		if(!var)
			return 0.0f;
		return var->m_value;
	}

	bool CoreSystem::SetVariableName(const VariableHandle& handle, const char* name, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return false;

		Variable* var = xmlData->GetVariable(handle);
		if(!var)
			return false;
		var->m_name = name;
		return true;
	}

	bool CoreSystem::SetVariableMin(const VariableHandle& handle, float min, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return false;

		Variable* var = xmlData->GetVariable(handle);
		if(!var)
			return false;
		var->m_min = min;
		return true;
	}

	bool CoreSystem::SetVariableMax(const VariableHandle& handle, float max, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return false;

		Variable* var = xmlData->GetVariable(handle);
		if(!var)
			return false;
		var->m_max = max;
		return true;
	}

	bool CoreSystem::SetVariableInitial(const VariableHandle& handle, float initial, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return false;

		Variable* var = xmlData->GetVariable(handle);
		if(!var)
			return false;
		var->m_initial = initial;
		return true;
	}

	bool CoreSystem::SetVariableValue(const VariableHandle& handle, float value, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return false;

		Variable* var = xmlData->GetVariable(handle);
		if(!var)
			return false;
		var->m_value = value;
		return true;
	}

	bool CoreSystem::RemoveVariable(const VariableHandle& handle, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return false;

		return xmlData->RemoveVariable(handle);
	}

	// Graph management
	Graph* CoreSystem::getGraphData(XMLFileHandle xmlFile, const GraphHandle& graphID)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0;

		return xmlData->GetGraph(graphID);
	}
	GraphHandle	CoreSystem::NewGraph(const char* graphName, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0;

		return xmlData->NewGraph(graphName);
	}

	GraphHandle CoreSystem::GetGraphHandle(const char* name, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0;

		return xmlData->GetGraphHandle(name);
	}
	GraphHandle	CoreSystem::GetGraphHandle(bool first, XMLFileHandle xmlFile )
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0;
		
		return xmlData->GetGraphHandle(first);
	}

	bool CoreSystem::ClearGraph(const GraphHandle& graphID, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return false;

		Graph* graph = xmlData->GetGraph(graphID);
		if(!graph)
			return false;

		graph->ClearGraph();
		return true;
	}

	bool CoreSystem::RemoveGraph(const GraphHandle& graphID, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return false;

		return xmlData->RemoveGraph(graphID);
	}

	const char* CoreSystem::GetGraphName(const GraphHandle& graphID, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return NULL;

		Graph* graph = xmlData->GetGraph(graphID);
		if(!graph)
			return NULL;

		return graph->m_name.c_str();
	}

	bool CoreSystem::SetGraphName(const GraphHandle& graphID, const char* name, XMLFileHandle xmlFile)
	{
		Graph* graph = getGraphData(xmlFile,graphID);
		if(!graph)
			return false;

		graph->m_name = name;
		return true;
	}

	bool CoreSystem::AddPoint(const GraphHandle& graphID, float x, float y, XMLFileHandle xmlFile)
	{
		Graph* graph = getGraphData(xmlFile,graphID);
		if(!graph)
			return false;

		graph->AddPoint(x,y);
		graph->SortPoints();
		return true;
	}

	bool CoreSystem::StopEvents()
	{
		// Loop through events and stop all channels
		eventlist_t::iterator iter = m_activeEvents.begin();
		while(iter != m_activeEvents.end()) {
			Event* event = *iter;
			subeventlist_t::iterator sub_iter = event->GetActiveSubEvents().begin();
			while(sub_iter != event->GetActiveSubEvents().end()) {
				StopSound((*sub_iter)->GetChannelHandle());
				++sub_iter;
			}
			delete event;
			iter = m_activeEvents.erase(iter);
		}
		return true;
	}

	float CoreSystem::GetGraphOutput(const GraphHandle& handle, float input, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0.0f;

		Graph* graph = xmlData->GetGraph(handle);
		if(!graph)
			return 0.0f;

		return graph->Compute(input);
	}

	unsigned CoreSystem::GetPointCount(const GraphHandle& graphID, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0;

		Graph* graph = xmlData->GetGraph(graphID);
		if(!graph)
			return 0;

		return (unsigned)graph->m_points.size();
	}
	float CoreSystem::GetPointX(const GraphHandle& graphID, unsigned index, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0;

		Graph* graph = xmlData->GetGraph(graphID);
		if(!graph)
			return 0;

		if( index < graph->m_points.size() )
			return graph->m_points[index].m_x;
		return 0;
	}
	float CoreSystem::GetPointY(const GraphHandle& graphID, unsigned index, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0;

		Graph* graph = xmlData->GetGraph(graphID);
		if(!graph)
			return 0;

		if( index < graph->m_points.size() )
			return graph->m_points[index].m_y;
		return 0;	
	}


	// Events, SubEvents & Effects
	EventData* CoreSystem::getEventData(XMLFileHandle xmlFile, const EventHandle& eventID)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0;

		return xmlData->GetEventData(eventID);
	}
	SubEventData* CoreSystem::getSubEventData(XMLFileHandle xmlFile, const EventHandle& eventID, const SubEventHandle& subID )
	{
		EventData* event = getEventData(xmlFile, eventID);
		if( !event )
			return 0;
		
		subeventdatamap_t::iterator iter = event->m_subEvents.find(subID);
		if(iter == event->m_subEvents.end())
			return 0;
	
		return iter->second;
	}
	EffectData* CoreSystem::getEffectData( XMLFileHandle xmlFile, const EventHandle& eventID, const SubEventHandle& subID, const EffectHandle& fxID ) 
	{
		SubEventData* subData = getSubEventData(xmlFile, eventID, subID);
		if( !subData )
			return 0;

		effectdatamap_t::iterator iter = subData->m_effects.find(fxID);
		if(iter == subData->m_effects.end())
			return 0;

		return iter->second;
	}

	EventHandle	CoreSystem::NewEvent(const char* name, bool looping, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0;

		return xmlData->NewEvent(name, looping);
	}

	EventHandle CoreSystem::GetEventHandle(bool first, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0;
		
		return xmlData->GetEventHandle(first);
	}
	bool CoreSystem::RemoveEvent(const EventHandle& eventID, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return false;

		return xmlData->RemoveEventData(eventID);
	}

	SubEventHandle CoreSystem::AddSubEvent(const EventHandle& eventID, const char* soundName, float triggerTime, int pitchShift, bool streaming, XMLFileHandle xmlFile)
	{
		Audio::XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0;

		EventData*	 event	 = getEventData(xmlFile, eventID);
		if(!event)
			return 0;

		SubEventHandle	subHandle = xmlData->UniqueSubEventHandle();
		SubEventData*	subEvent	= new SubEventData(soundName,triggerTime,pitchShift,streaming);
		event->m_subEvents.insert(subeventdatapair_t(subHandle,subEvent));
		return subHandle;
	}

	bool CoreSystem::RemoveSubEvent(const EventHandle& eventID, const SubEventHandle& subID, XMLFileHandle xmlFile)
	{
		EventData* event = getEventData(xmlFile, eventID);

		subeventdatamap_t::iterator iter = event->m_subEvents.find(subID);
		if(iter == event->m_subEvents.end())
			return false;

		delete iter->second;
		event->m_subEvents.erase(iter);
		return true;
	}

	EffectHandle CoreSystem::AddSoundEffect(const EventHandle& eventID, const SubEventHandle& subID, const char* graphName, const char* varName, unsigned effect, XMLFileHandle xmlFile)
	{
		SubEventData* subEvent = getSubEventData(xmlFile, eventID, subID);
		if( !subEvent )
			return false;

		EffectData* data = new EffectData(graphName,varName,effect);
		subEvent->m_effects.insert(effectdatapair_t(effect,data));
		return (EffectHandle)effect;
	}

	EffectHandle CoreSystem::AddSoundEffect(const EventHandle& eventID, const SubEventHandle& subID, const GraphHandle& graphID, const VariableHandle& varID, unsigned effect, XMLFileHandle xmlFile)
	{
		// Get names
		Graph*	graph = getGraphData(xmlFile, graphID);
		if(!graph)
			return 0;
		std::string graphName = graph->m_name;

		Variable* var = getVariableData(xmlFile, varID);
		if(!var)
			return 0;
		
		SubEventData*	subEvent	= getSubEventData(xmlFile, eventID, subID);
		if( !subEvent )
			return 0;

		std::string		varName		= var->m_name;
		EffectData*		data		= new EffectData(graphName,varName,effect);
		subEvent->m_effects.insert(effectdatapair_t(effect,data));
		return (EffectHandle)effect;
	}

	bool CoreSystem::RemoveSoundEffect(const EventHandle& eventID, const SubEventHandle& subID, const EffectHandle& effect, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return false;

		EventData* event = xmlData->GetEventData(eventID);
		if(!event)
			return false;

		subeventdatamap_t::iterator iter = event->m_subEvents.find(subID);
		if(iter == event->m_subEvents.end())
			return false;

		SubEventData* subEvent = iter->second;
		effectdatamap_t::iterator effect_iter = subEvent->m_effects.find(effect);
		if(effect_iter == subEvent->m_effects.end())
			return false;

		delete effect_iter->second;
		subEvent->m_effects.erase(effect_iter);
		return true;
	}

	const char* CoreSystem::GetEventName(const EventHandle& eventID, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return 0;
		
		EventData* event = xmlData->GetEventData(eventID);
		if(!event)
			return 0;
		
		return event->m_name.c_str();
	}
	bool CoreSystem::GetEventLooping( const EventHandle& eventID, XMLFileHandle xmlFile )
	{
		EventData*	 event	 = getEventData(xmlFile, eventID);
		if(!event)
			return false;

		return event->m_looping;
	}

	SubEventHandle CoreSystem::GetSubEventHandle(const EventHandle& eventID, bool first, XMLFileHandle xmlFile )
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if( !xmlData )
			return 0;

		return xmlData->GetSubEventHandle( eventID, first );
	}
	const char*	CoreSystem::GetSoundName( const EventHandle& eventID, const SubEventHandle& subID, XMLFileHandle xmlFile )
	{
		SubEventData* subData = getSubEventData(xmlFile, eventID, subID);
		if(!subData)
			return 0;
		
		return subData->m_soundName.c_str();
	}
	float CoreSystem::GetTriggerTime( const EventHandle& eventID, const SubEventHandle& subID, XMLFileHandle xmlFile )
	{
		SubEventData* subData = getSubEventData(xmlFile, eventID, subID);
		if(!subData)
			return 0;

		return subData->m_trigger;
	}

	int	CoreSystem::GetPitchShift( const EventHandle& eventID, const SubEventHandle& subID, XMLFileHandle xmlFile )
	{
		SubEventData* subData = getSubEventData(xmlFile, eventID, subID);
		if(!subData)
			return 0;

		return subData->m_pitchShift;
	}

	bool CoreSystem::GetStreaming( const EventHandle& eventID, const SubEventHandle& subID,	XMLFileHandle xmlFile )
	{
		SubEventData* subData = getSubEventData(xmlFile, eventID, subID);
		if(!subData)
			return 0;

		return subData->m_streaming;
	}
	EffectHandle CoreSystem::GetEffectHandle( const EventHandle& eventID, const SubEventHandle& subID, bool first, XMLFileHandle xmlFile )
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if( !xmlData )
			return 0;

		return xmlData->GetEffectHandle( eventID, subID, first );
	}
	GraphHandle	CoreSystem::GetEffectGraph( const EventHandle& eventID, const SubEventHandle& subID, const EffectHandle& fxID, XMLFileHandle xmlFile )
	{
		EffectData*  fxData = getEffectData(xmlFile, eventID, subID, fxID);
		if( !fxData )
			return 0;

		return GetGraphHandle( fxData->m_graph.c_str(), xmlFile );
	}
	VariableHandle CoreSystem::GetEffectVariable( const EventHandle& eventID, const SubEventHandle& subID, const EffectHandle& fxID, XMLFileHandle xmlFile )
	{
		EffectData*  fxData = getEffectData(xmlFile, eventID, subID, fxID);
		if( !fxData )
			return 0;

		return GetVariableHandle( fxData->m_variable.c_str(), xmlFile );
	}
	unsigned CoreSystem::GetEffectType( const EventHandle& eventID,	const SubEventHandle& subID, const EffectHandle& fxID, XMLFileHandle xmlFile )
	{
		EffectData*  fxData = getEffectData(xmlFile, eventID, subID, fxID);
		if( !fxData )
			return 0;

		return fxData->m_type;
	}

	// Sound path management
	bool CoreSystem::SetSoundPath(const char* path, XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return false;

		xmlData->m_path = path;
		return true;
	}

	const char* CoreSystem::GetSoundPath(XMLFileHandle xmlFile)
	{
		XMLAudioData* xmlData = GetXMLAudioData(xmlFile);
		if(!xmlData)
			return NULL;

		return xmlData->m_path.c_str();
	}

	XMLFileHandle CoreSystem::LoadSoundXML(const char file[])
	///////////////////////////////////////////////////////////////////////////////
	// Description: Reads an XML file and loads all data types into memory
	//
	// Recent Changes:
	// -brasmuss 4/10/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		// Is XML file already loaded?
		handlemap_t::iterator iter = m_xmlHandles.find(std::string(file));
		if(iter != m_xmlHandles.end())
			return 0;

		// Create
		XMLFileHandle handle	= UniqueXMLFileHandle();
		XMLAudioData* xmlData	= new XMLAudioData(std::string(file), handle);

		// Store
		m_xmlData.insert(xmldatapair_t(handle,xmlData));
		m_xmlHandles.insert(handlepair_t(std::string(file),handle));

		if(!xmlData->LoadSoundXML(file,this))
		{
			m_xmlHandles.erase( m_xmlHandles.find(std::string(file)) );
			m_xmlData.erase(	m_xmlData.find(handle) );
			delete xmlData;
			return 0;
		}

		return handle;
	}

	bool CoreSystem::UnloadSoundXML( XMLFileHandle handle )
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 4/10/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		// Is XML file already loaded?
		xmldatamap_t::iterator iter = m_xmlData.find(handle);
		if(iter == m_xmlData.end())
			return false;

		// Release
		XMLAudioData* data = iter->second;
		handlemap_t::iterator hand_iter = m_xmlHandles.find(data->m_file);
		m_xmlData.erase(iter);
		m_xmlHandles.erase(hand_iter);
		delete data;
		return true;
	}

	bool CoreSystem::SaveSoundXML( XMLFileHandle handle, const char* saveAs )
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 4/10/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		// Is XML file already loaded?
		xmldatamap_t::iterator iter = m_xmlData.find(handle);
		if(iter == m_xmlData.end())
			return false;

		// Save
		return iter->second->SaveSoundXML(saveAs);
	}

	XMLFileHandle CoreSystem::LoadBlankXML( const char* name )
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 4/11/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		// Is XML file already loaded?
		handlemap_t::iterator iter = m_xmlHandles.find(std::string(name));
		if(iter != m_xmlHandles.end())
			return 0;

		// Create
		XMLFileHandle handle = UniqueXMLFileHandle();
		XMLAudioData* xmlData = new XMLAudioData(std::string(name), handle);

		// Store
		m_xmlData.insert(xmldatapair_t(handle,xmlData));
		m_xmlHandles.insert(handlepair_t(std::string(name),handle));
		return handle;
	}

	XMLFileHandle CoreSystem::GetXMLHandle( const char* file )
	///////////////////////////////////////////////////////////////////////////////
	// Description: 
	//
	// Recent Changes:
	// -brasmuss 4/11/2007 : Created
	///////////////////////////////////////////////////////////////////////////////
	{
		handlemap_t::iterator iter = m_xmlHandles.find(std::string(file));
		if(iter == m_xmlHandles.end())
			return 0;
		return iter->second;
	}




	void CoreSystem::Clear()
	{
		for( xmldatamap_t::iterator itt = m_xmlData.begin(); itt != m_xmlData.end(); ++itt )
		{
			itt->second->Clear();
		}
		m_xmlData.clear();
		m_xmlHandles.clear();
	}

	//VariableHandle CoreSystem::CreateVariable(const char* name, float min, float max, float value, XMLFileHandle& xmlFile)
	//	///////////////////////////////////////////////////////////////////////////////
	//	// Description: Creates a variable with
	//	//
	//	// Recent Changes:
	//	// -brasmuss 3/30/2007 : Created
	//	///////////////////////////////////////////////////////////////////////////////
	//{
	//	std::string str(name);
	//	VariableHandle vHandle = UniqueVarHandle();
	//	Variable* var = new Variable(str,min,max,value,vHandle);
	//	// Store the variable
	//	m_varPool.insert(variablepair_t(vHandle,var));
	//	// Store the handle
	//	m_varHandles.insert(handlepair_t(str,vHandle));
	//	return vHandle;
	//}

	//GraphHandle CoreSystem::CreateGraph(const char* /*name*/ /* list of points*/)
	//	///////////////////////////////////////////////////////////////////////////////
	//	// Description: Creates a graph from a list of points
	//	//
	//	// Recent Changes:
	//	// -brasmuss 3/30/2007 : Created
	//	///////////////////////////////////////////////////////////////////////////////
	//{
	//	GraphHandle gHandle = UniqueGraphHandle();

	//	// TEST
	//	pointlist_t points;
	//	points.push_back(Point(0.0f,0.0f));
	//	points.push_back(Point(1.0f,1.0f));
	//	// END TEST

	//	Graph* graph = new Graph(points);
	//	m_graphPool.insert(graphpair_t(gHandle,graph));
	//	return gHandle;
	//}

	//Graph* CoreSystem::GetGraph(GraphHandle& handle)
	//{
	//	graphmap_t::iterator iter = m_graphPool.find(handle);
	//	if(iter != m_graphPool.end())
	//		return iter->second;
	//	return NULL;
	//}

	//bool CoreSystem::SetVariable(const VariableHandle& handle, float value)
	//	///////////////////////////////////////////////////////////////////////////////
	//	// Description: Finds a variable and sets the value.  Returns false if
	//	//				variable doesn't exist or value is out of range.
	//	//
	//	// Recent Changes:
	//	// -brasmuss 3/30/2007 : Created
	//	///////////////////////////////////////////////////////////////////////////////
	//{
	//	variablemap_t::iterator iter = m_varPool.find(handle);
	//	if(iter == m_varPool.end())
	//		return false;
	//	return iter->second->SetValue(value);
	//}

	//bool CoreSystem::GetVarHandle(const char* name, VariableHandle& handle)
	//	///////////////////////////////////////////////////////////////////////////////
	//	// Description: Searches the map of string/handle pairs.  Returns false if
	//	//				it doesn't exist
	//	//
	//	// Recent Changes:
	//	// -brasmuss 3/30/2007 : Created
	//	///////////////////////////////////////////////////////////////////////////////
	//{
	//	std::string str(name);
	//	handlemap_t::iterator iter = m_varHandles.find(str);
	//	if(iter == m_varHandles.end())
	//		return false;
	//	handle = iter->second;
	//	return true;
	//}

	//bool CoreSystem::CreateEvent(const char* /*name*/)
	//	///////////////////////////////////////////////////////////////////////////////
	//	// Description: Creates the event and puts it on the active list
	//	//
	//	// Recent Changes:
	//	// -brasmuss 3/30/2007 : Created
	//	///////////////////////////////////////////////////////////////////////////////
	//{
	//	// TODO, actually look into loaded category and create event from XML data
	//	// Temp values
	//	FileHandle fHandle0, fHandle1;
	//	if(!LoadSoundFile(L"LongSound.wav",fHandle0))
	//		return false;
	//	if(!LoadSoundFile(L"cluck.wav",fHandle1))
	//		return false;
	//	GraphHandle gHandle = CreateGraph(NULL);
	//	VariableHandle vHandle = CreateVariable("Var0",0.0f,1.0f,0.0f);

	//	Event* event = new Event;

	//	// Loop through and add all sub events
	//	SubEvent* subEvent0 = new SubEvent(fHandle0);
	//	SubEvent* subEvent1 = new SubEvent(fHandle1);
	//	subEvent0->AddEffect(new Effect(gHandle,vHandle,EffectGain));
	//	subEvent1->AddEffect(new Effect(gHandle,vHandle,EffectPan));

	//	event->AddSubEvent(subEvent0,5000.0f);
	//	event->AddSubEvent(subEvent1,10000.0f);

	//	m_activeEvents.push_back(event);

	//	return true;
	//}

	//float CoreSystem::GetVariableValue(VariableHandle& handle)
	//	///////////////////////////////////////////////////////////////////////////////
	//	// Description: 
	//	//
	//	// Recent Changes:
	//	// -brasmuss 3/30/2007 : Created
	//	///////////////////////////////////////////////////////////////////////////////
	//{
	//	variablemap_t::iterator iter = m_varPool.find(handle);
	//	if(iter == m_varPool.end())
	//		return 0.0f;
	//	return iter->second->GetValue();
	//}

	//float CoreSystem::GetGraphOutput(GraphHandle& graph, float input)
	//	///////////////////////////////////////////////////////////////////////////////
	//	// Description: Finds the graph and computes the output value
	//	//
	//	// Recent Changes:
	//	// -brasmuss 3/30/2007 : Created
	//	///////////////////////////////////////////////////////////////////////////////
	//{
	//	graphmap_t::iterator iter = m_graphPool.find(graph);
	//	if(iter == m_graphPool.end())
	//		return 0.0f;
	//	return iter->second->Compute(input);
	//}B
}
